1 00:00:00,690 --> 00:00:01,230 Okay. 2 00:00:01,230 --> 00:00:06,660 In this lecture, we're going to expand our knowledge of client to server communication by using remote 3 00:00:06,660 --> 00:00:08,670 events and remote functions. 4 00:00:08,820 --> 00:00:14,130 A remote event is an instance in our game that allows the client to communicate to the server, or it 5 00:00:14,130 --> 00:00:16,620 allows the server to communicate to the client. 6 00:00:16,710 --> 00:00:23,040 A remote event can have a function called upon it, which is either a fire server or fire client, which 7 00:00:23,040 --> 00:00:26,030 triggers an event on either the client or the server. 8 00:00:26,040 --> 00:00:30,960 Any scripts in our game that are listening to those events get executed, and they can also be passed 9 00:00:30,960 --> 00:00:33,760 information from our client or from the server. 10 00:00:33,780 --> 00:00:37,890 So I'm going to create a new remote event inside of our replicated storage. 11 00:00:37,890 --> 00:00:41,250 That way both the client and the server can access it. 12 00:00:41,250 --> 00:00:44,150 And we're just going to add in here a new remote event. 13 00:00:44,160 --> 00:00:47,940 And I'm not going to change the name, I'm just going to leave it at Remote Event for now. 14 00:00:47,940 --> 00:00:52,980 And then I'm going to create a new server script in our server script service, and then a new local 15 00:00:52,980 --> 00:00:55,890 script inside of the starter player scripts. 16 00:00:55,890 --> 00:01:01,740 And to demonstrate this client to server communication, we're going to make a reference to our remote 17 00:01:01,740 --> 00:01:05,790 event by first getting the service that it's stored in, which is replicated storage. 18 00:01:05,790 --> 00:01:09,330 So I'm going to call this variable replicated Storage. 19 00:01:09,330 --> 00:01:10,620 And that's equal to game. 20 00:01:10,620 --> 00:01:13,260 And we're going to get the service replicated storage. 21 00:01:13,470 --> 00:01:17,580 And then we can copy this and do the exact same thing for our server script. 22 00:01:17,910 --> 00:01:21,480 And then inside of replicated storage we need to access that remote event. 23 00:01:21,480 --> 00:01:23,030 So I'll create a variable for it. 24 00:01:23,040 --> 00:01:24,420 I'll just call it event. 25 00:01:24,420 --> 00:01:28,230 And that's equal to replicated storage dot remote event. 26 00:01:28,230 --> 00:01:32,130 And again we can copy this and do the exact same thing on the server. 27 00:01:32,950 --> 00:01:38,530 And what I want to do on the client is I want to refer to my event, and I want to use a function called 28 00:01:38,530 --> 00:01:39,880 Fire Server. 29 00:01:39,910 --> 00:01:45,220 And what this function does is it allows us to trigger the event on the server, which is the on server 30 00:01:45,220 --> 00:01:49,320 event, and pass any additional information we would like to the server. 31 00:01:49,330 --> 00:01:54,940 So inside these two parentheses is where we can pass information such as strings, numbers, other instances 32 00:01:54,940 --> 00:01:55,990 and things like that. 33 00:01:55,990 --> 00:02:00,700 So for demonstration's sake I'm just going to pass a string that says hello. 34 00:02:01,660 --> 00:02:06,460 And then on the server script, what we're going to do is we're going to listen to that event. 35 00:02:06,460 --> 00:02:11,920 So we're going to refer to our remote event and then index it and get the on server event. 36 00:02:11,920 --> 00:02:15,220 So this event gets fired for our server scripts. 37 00:02:15,220 --> 00:02:17,890 And then we need to connect a function to this remote event. 38 00:02:17,890 --> 00:02:23,770 So we're going to connect and create a new lambda function or a function that has no identifier. 39 00:02:23,770 --> 00:02:29,650 And what gets passed to this function is first off it's going to tell us the player that fired this 40 00:02:29,650 --> 00:02:32,920 event, it's always going to be the first thing passed to this function. 41 00:02:32,920 --> 00:02:34,690 We're going to get a player instance. 42 00:02:34,690 --> 00:02:37,120 And this is the player who triggered the event. 43 00:02:37,120 --> 00:02:42,100 After the player, we can get all of the other information that gets passed to our function. 44 00:02:42,100 --> 00:02:44,920 So in this case we were expecting a string. 45 00:02:44,920 --> 00:02:51,040 So we can just call this parameter here example string. 46 00:02:51,930 --> 00:02:55,410 And then we can go ahead and print out the result inside of the console. 47 00:02:55,410 --> 00:02:58,200 And what I'm going to do is I'm going to print out the player's name. 48 00:02:58,320 --> 00:03:01,530 And then I'm also going to print out whatever they pass to the server. 49 00:03:01,530 --> 00:03:03,750 In this case that's our example string. 50 00:03:04,400 --> 00:03:10,760 So now when I go and run the game, we refer to the exact same event, and then we fire to the server 51 00:03:10,760 --> 00:03:15,050 to trigger the on server event and we pass the information of hello. 52 00:03:15,080 --> 00:03:18,980 So that means when this event gets triggered this function is going to execute. 53 00:03:18,980 --> 00:03:21,770 It's going to tell us the player that triggered this event. 54 00:03:21,770 --> 00:03:26,300 And then it's going to also pass whatever information the client passed to the server. 55 00:03:26,300 --> 00:03:28,400 In this case that is our string. 56 00:03:28,670 --> 00:03:35,270 So if we go ahead and play test our game, as you can see we get the name of our account printed out. 57 00:03:35,270 --> 00:03:40,310 And as you can see we also get the string of hello which we passed from the client to the server. 58 00:03:40,960 --> 00:03:43,390 Again, we can pass as much information as we'd like here. 59 00:03:43,390 --> 00:03:49,590 We can pass a bunch of numbers, and then here I'll just make this parameter variadic. 60 00:03:49,600 --> 00:03:54,670 And then we can just print out all of those variadic results into the console. 61 00:03:54,670 --> 00:03:55,780 So if I hit run. 62 00:03:56,670 --> 00:04:02,850 As you can see, we get one, two, three and four, and the only limitations with sending information 63 00:04:02,850 --> 00:04:07,200 through remote events are going to be tables that have mixed indexes. 64 00:04:07,200 --> 00:04:12,990 So for example, you can't pass a table to the server that has a mixture of keys and also has a mixture 65 00:04:12,990 --> 00:04:13,770 of indexes. 66 00:04:13,770 --> 00:04:14,960 Those won't work. 67 00:04:14,970 --> 00:04:18,720 And you also can't pass meta tables through remote events. 68 00:04:18,720 --> 00:04:23,610 So if you had a table with a meta table attached to it, and you try to send that to the client or the 69 00:04:23,610 --> 00:04:29,250 server, the table itself would be fine, but it would lose the meta table attached to it through that 70 00:04:29,250 --> 00:04:32,730 transfer from the client to the server or the server to the client. 71 00:04:32,730 --> 00:04:34,350 So that's just important to note. 72 00:04:34,350 --> 00:04:40,080 You can't pass meta tables through remote events, and you can't pass mixed tables through remote events. 73 00:04:40,710 --> 00:04:45,990 Now, another important thing you've got to be careful of is that the client can send whatever information 74 00:04:45,990 --> 00:04:47,250 they want to the server. 75 00:04:47,250 --> 00:04:52,050 So if you have any exploiters or hackers in your game, they can try to mess with your remote events 76 00:04:52,050 --> 00:04:54,330 and cause stuff that you don't want to happen. 77 00:04:54,330 --> 00:05:00,030 For example, if you ever had a tool in your game that dealt damage to other players and you made the 78 00:05:00,030 --> 00:05:05,970 mistake of passing the value of how much damage you're supposed to deal to the other player, well, 79 00:05:05,970 --> 00:05:12,510 if we fire this event and the server took, let's say that damage and then use that damage to apply 80 00:05:12,510 --> 00:05:15,540 it on another player that can be easily exploited. 81 00:05:15,570 --> 00:05:21,990 A hacker could fire this event and pass whatever number they'd like here, like a huge number to instantly 82 00:05:21,990 --> 00:05:23,070 kill the other player. 83 00:05:23,070 --> 00:05:28,530 So you always have to be mindful of the information that the client is passing to the server. 84 00:05:28,530 --> 00:05:32,550 You got to make sure that the information is correct, and you also got to make sure that they're not 85 00:05:32,550 --> 00:05:36,750 manipulating or being malicious with whatever information they're trying to send. 86 00:05:36,810 --> 00:05:43,050 And you should always script your code in a way where you don't have to pass how much damage to deal 87 00:05:43,080 --> 00:05:48,330 to another player through remote events that should instead be stored in some kind of property for the 88 00:05:48,330 --> 00:05:53,010 tool that the server can read without having to get that information from the client. 89 00:05:53,010 --> 00:05:57,030 Because, again, you never want to trust the information that is coming from the client. 90 00:05:57,030 --> 00:06:02,070 You always want to verify the information because you never know if it's an exploiter trying to mess 91 00:06:02,070 --> 00:06:02,940 with your game. 92 00:06:03,600 --> 00:06:08,040 Now let's go ahead and also demonstrate this working in the other direction. 93 00:06:08,040 --> 00:06:14,490 So if I would like the server to fire to a particular player, then what we could do is we could refer 94 00:06:14,490 --> 00:06:19,740 to our event and use a function called fire client, or we could use fire all clients. 95 00:06:19,740 --> 00:06:25,830 So fire client triggers an event for a particular player, while fire all clients triggers the event 96 00:06:25,830 --> 00:06:28,020 for every single player that's inside of your game. 97 00:06:28,020 --> 00:06:34,260 For this particular example, we're going to use fire all clients, and if you were to use the regular 98 00:06:34,260 --> 00:06:38,550 fire clients, you would have to specify the player that you would like the event to trigger for. 99 00:06:38,550 --> 00:06:41,460 But for fire all clients, we don't need to. 100 00:06:41,460 --> 00:06:45,660 And from here we can pass whatever information we would like to our clients. 101 00:06:45,660 --> 00:06:50,340 In some cases, you might not need to send any information, and in other cases you might want to send 102 00:06:50,340 --> 00:06:53,490 some information like strings or numbers or whatever the case may be. 103 00:06:53,490 --> 00:06:58,080 So in this case, I'm just going to send a string to the client and I'm just going to call it howdy. 104 00:06:58,410 --> 00:07:06,540 And then here on our local script, what we're going to do is we're going to refer to our event, and 105 00:07:06,540 --> 00:07:12,000 we're going to listen to the on client event and connect a Lambda function to this. 106 00:07:13,030 --> 00:07:16,690 And then we can get the string that the server is going to pass here. 107 00:07:16,690 --> 00:07:18,670 So I'll just call this example string. 108 00:07:18,700 --> 00:07:21,970 And then we can go ahead and print this out into the console. 109 00:07:22,240 --> 00:07:29,710 Now something you need to note is that since this server script is going to execute immediately when 110 00:07:29,710 --> 00:07:36,640 we fire this event to our clients, our player may not have loaded the game yet and have and has executed 111 00:07:36,640 --> 00:07:37,380 this script. 112 00:07:37,390 --> 00:07:40,150 So that means the server fires this event. 113 00:07:40,150 --> 00:07:44,330 But we aren't listening to it yet because this script hasn't been executed. 114 00:07:44,350 --> 00:07:47,920 So to account for that, I'm going to put a delay in here. 115 00:07:47,920 --> 00:07:54,640 We'll use task Dot wait and we're going to wait 10s before we fire to our player in this particular 116 00:07:54,640 --> 00:07:55,450 instance. 117 00:07:55,630 --> 00:08:01,270 So that gives us enough time to load into our game and then connect a function to the on client event 118 00:08:01,270 --> 00:08:05,200 and listen for when we get that string passed to us. 119 00:08:05,350 --> 00:08:07,270 So if we go and play test again. 120 00:08:08,350 --> 00:08:13,300 As you can see, we pass information to the server and then we should wait and we should get information 121 00:08:13,300 --> 00:08:15,010 passed back to the client. 122 00:08:16,290 --> 00:08:17,460 Any second now. 123 00:08:17,460 --> 00:08:18,420 And there we go. 124 00:08:18,450 --> 00:08:21,840 Our client printed out the string that was on the server, which was howdy. 125 00:08:22,480 --> 00:08:25,020 So this is how we can use remote events. 126 00:08:25,030 --> 00:08:30,490 Any time you would like to listen to a remote event on the client, we use the on client event. 127 00:08:30,490 --> 00:08:35,470 And any time we would like to pass information to the server from the client, we use the fire server 128 00:08:35,470 --> 00:08:36,220 function. 129 00:08:36,220 --> 00:08:41,950 And then here on the server, whenever we would like to listen to a remote event, we use the on server 130 00:08:41,950 --> 00:08:42,700 event. 131 00:08:42,700 --> 00:08:48,160 And then any time we would like to send information to players in our game, we can use the fire client 132 00:08:48,160 --> 00:08:50,290 or Fire all clients function. 133 00:08:50,740 --> 00:08:54,040 Okay, now let's go ahead and take a look at a remote function. 134 00:08:54,070 --> 00:09:00,570 A remote function is one we use when we would like to grab or receive information from the server. 135 00:09:00,580 --> 00:09:07,120 When we trigger or invoke a remote function, our script is going to yield until that remote function 136 00:09:07,120 --> 00:09:09,170 returns information back to us. 137 00:09:09,190 --> 00:09:11,230 This can be useful in many situations. 138 00:09:11,230 --> 00:09:15,610 For example, maybe you have a door in your game that needs a special passcode. 139 00:09:15,610 --> 00:09:20,680 For security reasons, you would not want to store that password on the client, but instead you would 140 00:09:20,680 --> 00:09:26,020 like to store that password on the server in order to verify that the password the client enters is 141 00:09:26,020 --> 00:09:26,590 correct. 142 00:09:26,620 --> 00:09:32,020 We can give the server the password through a remote function, and then the server can verify if that 143 00:09:32,020 --> 00:09:37,300 password is correct or not, and then it can return back to us information telling us if we got it right 144 00:09:37,300 --> 00:09:37,960 or not. 145 00:09:38,080 --> 00:09:43,480 There are many use cases for remote functions, however, one use case you would not want to use is 146 00:09:43,480 --> 00:09:48,910 having the server invoke a client and wait for that client to send information back to the server. 147 00:09:48,940 --> 00:09:54,490 This is an unreliable practice, because a player could leave the game right when the server tries to 148 00:09:54,490 --> 00:09:59,140 invoke the client, which would cause the server to be stuck in an infinite yield because the player 149 00:09:59,140 --> 00:10:02,050 left the game and won't send any information back to the server. 150 00:10:02,080 --> 00:10:07,540 So you'll want to use remote functions for clients invoking the server, but you do not want to use 151 00:10:07,540 --> 00:10:11,550 remote functions in the case of the server invoking a client. 152 00:10:11,560 --> 00:10:15,790 So we can go ahead and create a new remote function inside of replicated storage. 153 00:10:16,300 --> 00:10:18,610 So remote function, there we go. 154 00:10:18,880 --> 00:10:23,110 And then inside of my local script I deleted everything except for our service. 155 00:10:23,110 --> 00:10:25,870 And again we're going to create a variable called event. 156 00:10:25,870 --> 00:10:29,140 And this time we're going to refer to our remote function. 157 00:10:29,140 --> 00:10:34,090 So that's going to be equal to replicated storage dot remote function. 158 00:10:34,630 --> 00:10:37,510 And what we can do here is we can refer to this event. 159 00:10:37,510 --> 00:10:41,170 And we have to use a different function for this remote function. 160 00:10:41,170 --> 00:10:44,230 And this function is called invoke server. 161 00:10:44,230 --> 00:10:50,920 So this tells the server that we would like to execute the function attached to the on server invoke 162 00:10:50,920 --> 00:10:52,090 callback. 163 00:10:52,510 --> 00:10:56,620 And a callback is simply a function that's passed as an argument to another piece of code. 164 00:10:56,620 --> 00:11:01,840 In this case, you would store a function in a property inside of the remote function, and that function 165 00:11:01,840 --> 00:11:07,990 is expected to be executed or basically called back to execute whatever functionality we would like. 166 00:11:08,020 --> 00:11:11,410 In this case, that's retrieving information from the server. 167 00:11:11,410 --> 00:11:14,050 So we're going to use the invoke server function. 168 00:11:14,780 --> 00:11:19,130 And let's say we have a password we would like to pass like hello. 169 00:11:19,160 --> 00:11:20,740 Maybe that's the password. 170 00:11:20,750 --> 00:11:25,640 And then what we're going to do in our server script is again refer to that event and replicated storage. 171 00:11:25,640 --> 00:11:27,920 So our replicated storage remote function. 172 00:11:29,340 --> 00:11:32,070 And this time with our remote function. 173 00:11:32,070 --> 00:11:35,840 We have a property in there called on Server Invoke. 174 00:11:35,850 --> 00:11:40,260 And what we have to store on this property is a function that needs to be called. 175 00:11:40,380 --> 00:11:43,890 So we can auto fill in this property. 176 00:11:44,010 --> 00:11:46,830 And then we assign this property with a function. 177 00:11:46,830 --> 00:11:49,320 In this case we're going to create a lambda function here. 178 00:11:50,930 --> 00:11:56,660 And this lambda function is also going to be passed the player that invoked this remote function. 179 00:11:56,660 --> 00:12:00,800 And then we get passed any other additional information that the client has passed to us. 180 00:12:00,800 --> 00:12:03,440 In this case that is our password. 181 00:12:03,560 --> 00:12:07,910 And inside of here we can go ahead and store the correct password. 182 00:12:08,090 --> 00:12:11,000 And let's say the correct password is howdy. 183 00:12:12,140 --> 00:12:17,480 And then we can go ahead and check if the password the player passed to the server matches the correct 184 00:12:17,480 --> 00:12:18,260 password. 185 00:12:18,290 --> 00:12:24,740 So what we could do here is we could check if the password the player passed is equal to the correct 186 00:12:24,740 --> 00:12:25,610 password. 187 00:12:25,820 --> 00:12:32,600 If it is, then we can return true back to this player to let them know that hey, that was the correct 188 00:12:32,600 --> 00:12:33,160 password. 189 00:12:33,170 --> 00:12:38,870 Otherwise we could just return false telling them hey, the password was incorrect. 190 00:12:38,900 --> 00:12:44,120 So whatever we return from this function gets sent back to our player. 191 00:12:44,150 --> 00:12:50,930 So that means when we use the invoke server function, what this is going to return is whatever the 192 00:12:50,930 --> 00:12:52,250 server returns back to us. 193 00:12:52,250 --> 00:12:54,560 In this case we expect a boolean. 194 00:12:54,560 --> 00:12:56,630 So we could call this variable result. 195 00:12:56,990 --> 00:13:01,340 And that's equal to what gets returned from our invoke server function. 196 00:13:01,340 --> 00:13:05,180 And then we can go ahead and print that result out inside of the console. 197 00:13:05,250 --> 00:13:11,230 In this case, since our password does not match the word of howdy, we should get false printed here. 198 00:13:11,240 --> 00:13:13,100 So let's go ahead and see what happens. 199 00:13:13,930 --> 00:13:15,390 And as you can see, there we go. 200 00:13:15,400 --> 00:13:19,360 We get false printed into the console because our password was not correct. 201 00:13:20,370 --> 00:13:24,060 However, let's say we entered in the correct password, which is howdy. 202 00:13:24,920 --> 00:13:26,690 Then when we go and run our game. 203 00:13:27,460 --> 00:13:32,830 As you can see, we get true returned back to us, which is the server letting us know, hey, you got 204 00:13:32,830 --> 00:13:34,300 the password correct? 205 00:13:34,990 --> 00:13:35,350 Now. 206 00:13:35,350 --> 00:13:40,240 This remote function also has a property for the client which is on client invoke. 207 00:13:40,240 --> 00:13:45,970 But again, I don't recommend using this because there shouldn't be ever a circumstance where the server 208 00:13:45,970 --> 00:13:50,860 would need to invoke the client, and the client has to send information back to the server. 209 00:13:50,890 --> 00:13:52,840 That's just trouble waiting to happen. 210 00:13:52,870 --> 00:14:00,010 I don't recommend doing it because a I can't find a use case for ever needing to do that, and b you're 211 00:14:00,010 --> 00:14:03,040 going to run into problems when, let's say a player leaves your game. 212 00:14:03,040 --> 00:14:07,510 So don't use on client invoke and don't invoke clients from the server. 213 00:14:07,540 --> 00:14:08,890 There's no need to do that. 214 00:14:08,920 --> 00:14:13,870 The main purpose of your remote functions is to get information from the server. 215 00:14:14,610 --> 00:14:15,230 All righty. 216 00:14:15,300 --> 00:14:20,640 You should now have a basic idea of client to server communication, and how we can use remote events 217 00:14:20,640 --> 00:14:22,660 and remote functions in our scripts. 218 00:14:22,680 --> 00:14:24,840 I will see you in the next lecture.